package org.travelfusion.xmlclient.ri.handler.plane;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamReader;

import org.travelfusion.xmlclient.ri.xobject.plane.XCheckRoutingRequest;
import org.travelfusion.xmlclient.ri.xobject.plane.XFlight;
import org.travelfusion.xmlclient.ri.xobject.plane.XFlightSegment;

class FlightSubHandler {

  private final CheckRoutingHandler parent;
  private final FlightSegmentSubHandler segmentHandler;

  FlightSubHandler(CheckRoutingHandler parent) {
    this.parent = parent;
    this.segmentHandler = new FlightSegmentSubHandler(parent);
  }

  Map<String, String> getOperatorNames() {
    return segmentHandler.getOperatorNames();
  }

  private static enum State {
    ROOT, //
    PRICE, //
    TAX_ITEMS, //
    SEGMENTS
  }

  public XFlight handleResponse() throws Exception {
    XFlight flight = new XFlight();

    StringBuilder builder = new StringBuilder();
    String currentName = null;
    boolean build = false;

    int price = -1;
    List<XFlightSegment> segments = new ArrayList<XFlightSegment>(3);

    final XCheckRoutingRequest request = parent.getRequest();
    final XMLStreamReader responseReader = parent.getResponseReader();

    State state = State.ROOT;
    done: for (int event; ((event = responseReader.next()) != XMLStreamConstants.END_DOCUMENT);) {
      switch (event) {
        case XMLStreamConstants.START_ELEMENT:
          currentName = responseReader.getName().getLocalPart();
          builder.setLength(0);
          switch (state) {
            case ROOT:
              if ("Id".equals(currentName)) {
                build = true;
              }
              else if ("Price".equals(currentName)) {
                state = State.PRICE;
                price = -1;
              }
              else if ("Duration".equals(currentName)) {
                build = true;
              }
              else if ("SegmentList".equals(currentName)) {
                state = State.SEGMENTS;
              }
              break;
            case PRICE:
              if ("Amount".equals(currentName)) {
                price = 0;
                build = true;
              }
              else if ("TaxItemList".equals(currentName)) {
                state = State.TAX_ITEMS;
              }
              break;
            case SEGMENTS:
              if ("Segment".equals(currentName)) {
                segments.add(segmentHandler.handleResponse());
              }
              else if ("SegmentList".equals(currentName)) {
                state = State.ROOT;
              }
              break;
          }
          break;
        case XMLStreamConstants.CHARACTERS:
          if (build) {
            builder.append(responseReader.getTextCharacters(), responseReader.getTextStart(), responseReader.getTextLength());
          }
          break;
        case XMLStreamConstants.END_ELEMENT:
          currentName = responseReader.getName().getLocalPart();
          switch (state) {
            case ROOT:
              if ("Id".equals(currentName)) {
                flight.setId(builder.toString());
                build = false;
              }
              else if ("Duration".equals(currentName)) {
                flight.setDuration(Integer.parseInt(builder.toString()));
                build = false;
              }
              else if ("Outward".equals(currentName) || "Return".equals(currentName)) {
                break done;
              }
              break;
            case PRICE:
              if (price >= 0) {
                if ("Amount".equals(currentName)) {
                  flight.setPrice((int)Math.round(Double.parseDouble(builder.toString()) * 100));
                }
                else if ("Currency".equals(currentName)) {
                  flight.setCurrency(builder.toString());
                }
                else if ("PriceIncludesTax".equals(currentName)) {
                  flight.setTaxIncluded(Boolean.parseBoolean(builder.toString()));
                }
              }
              if ("Price".equals(currentName)) {
                state = State.ROOT;
                build = false;
              }
              break;
            case TAX_ITEMS:
              if ("TaxItemList".equals(currentName)) {
                state = State.PRICE;
              }
              break;
            case SEGMENTS:
              if ("SegmentList".equals(currentName)) {
                state = State.ROOT;
              }
              break;
          }
          break;
      }
    }

    if (!segments.isEmpty()) {
      XFlightSegment firstSegment = segments.get(0);
      XFlightSegment lastSegment = segments.get(segments.size() - 1);

      flight.setOrigin(firstSegment.getOrigin());
      flight.setDestination(lastSegment.getDestination());
      flight.setDepartureTime(firstSegment.getDepartureTime());
      flight.setArrivalTime(lastSegment.getArrivalTime());
      flight.setNumStops(segments.size() - 1);

      String[] operators = new String[segments.size()];
      for (int i = 0; i < segments.size(); i++) {
        operators[i] = segments.get(i).getOperator();
      }
      flight.setOperators(operators);
    }

    if (request.isSegmentsEnabled()) {
      flight.setSegments(segments);
    }

    return flight;
  }
}
